package com.techwells.taco.dataaccess;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.techwells.taco.utils.FileUtil;
import com.techwells.taco.utils.LogUtil;

/**
 * 参考类，数据库访问层，所有的数据库操作都只能通过该类访问
 */
class DataAccess {
	private final static String LOG = "dbLog";
	private final static String ERROR = "dbError";
	private DataBaseHelper helper = null;
	//the connection to database,use it to read and write database
	protected SQLiteDatabase connection = null;
	
	private static Context appContext = null;
	private static String name = null;
	private static int version = 0;
	
	/**
	 * 构造方法，new对象时区分操作数据库的access用做写还是读操作，一个access只做读或写操作
	 * @param isRead 是否只读数据库
	 */
	public DataAccess(boolean isRead) {
		helper = DataBaseHelper.shareInstance(appContext, name, version);
		if (isRead) {
			connection = helper.getReadConnection();
			LogUtil.d(LOG, "helper:"+helper.hashCode()+" readConnection:"+connection.hashCode());
		}else {
			connection = helper.getWriteConnection();
			LogUtil.d(LOG, "helper:"+helper.hashCode()+" writeConnection:"+connection.hashCode());
		}
	}
	
	/**
	 * 在app启动时做好数据库相关的初始化工作
	 * @param context	应用的上下文
	 * @param dbName	数据库名称
	 * @param dbVersion	数据库版本号
	 */
	public static void initDB(Context context,String dbName,int dbVersion) {
		appContext = context;
		name = dbName;
		version = dbVersion;
	}
	
	/**
	 * 用完access操作完数据库后需要调用关闭数据库方法
	 */
	public void closeDataBase() {
		helper.close();
	}
	
	/**
	 * 将raw目录下的数据库文件拷贝到系统默认数据库路径下（raw中的数据库文件名称只能使用小写字母）
	 * @param rawResourceId raw目录资源文件对应在gen.R.raw下的id（com.saike.android.包名.R.raw.数据库名）
	 */
	public static void copyDatabaseFile(int rawResourceId) {
		LogUtil.d(LOG, "start copy db file");
		//获取数据库目录路径，不存在则创建目录
		String dbPath = FileUtil.getDataBasePath(appContext);
        File dir = new File(dbPath);  
        if (!dir.exists()) {  
            try {  
                dir.mkdir();  
            } catch (Exception e) {  
                e.printStackTrace(); 
        		LogUtil.e(ERROR, "mkdir failed at "+dir); 
            }  
        }  
          
        File dest = new File(dir, name); 
          
        try {  
            if(dest.exists()){  
                return;  
            }
            //不存在数据库则将raw下的数据库拷贝到默认路径
            dest.createNewFile();     
            InputStream in = appContext.getResources().openRawResource(rawResourceId);  
            int size = in.available();  
            byte buf[] = new byte[size];  
            in.read(buf);  
            in.close();  
            FileOutputStream out = new FileOutputStream(dest);  
            out.write(buf);
            out.close();
            LogUtil.d(LOG, "copy db file success"); 
        } catch (Exception e) {  
            e.printStackTrace();  
        }
        LogUtil.d(LOG, "end copy db file");
    } 

	/**
	 * 查询数据库中数据表的数量
	 * 
	 * @return 数据库中表的数量
	 */
	public int queryTableNumbers() {
		int tables = 0;
		if (connection != null) {
			Cursor cursor = connection.rawQuery(
					"select count(*) from sqlite_master where type='table'",
					null);
			while (cursor.moveToNext()) {
				tables = cursor.getInt(0);
			}
			cursor.close();
		}
		return tables;
	}

	/**
	 * 查询表中的数据行数
	 * 
	 * @param tableName 查询的表名
	 * 
	 * @return 表中数据总行数
	 */
	public int queryRowsInTable(String tableName) {
		int rows = 0;
		Cursor cursor = connection.rawQuery("select * from " + tableName, null);
		while (cursor.moveToNext()) {
			rows++;
		}
		cursor.close();
		return rows;
	}

	/**
	 * 执行sql，可用于创建数据表和建立表索引等
	 * @param sql 数据库操作语句
	 * @return	执行成功与否
	 */
	public boolean executeSQL(String sql) {
		boolean result = false;
		if (connection != null) {
			connection.beginTransaction();
			connection.execSQL(sql);
			connection.setTransactionSuccessful();
			connection.endTransaction();
			result = true;
		}else {
			result = false;
		}
		return result;
	}
}